﻿using Newtonsoft.Json;

namespace Ocelot.Admin.Api.Application
{
    public class RouteService : IRouteService, ITransient
    {
        private readonly SqlSugarScopeProvider _sqlserverDB;
        private readonly IGlobalConfigurationService _globalConfigurationService;
        private readonly IProjectService _projectService;
        private readonly IRouteCacheService _routeCacheService;
        public RouteService(ISqlSugarClient db, IRouteCacheService routeCacheService,
            IGlobalConfigurationService globalConfigurationService, IProjectService projectService)
        {
            _sqlserverDB = db.AsTenant().GetConnectionScope(DatabaseConfigIdConst.OcelotSettings);
            _routeCacheService = routeCacheService;
            _globalConfigurationService = globalConfigurationService;
            _projectService = projectService;
        }

        #region 查询

        /// <summary>
        /// 预览路由信息
        /// </summary>
        /// <returns></returns>
        public async Task<string> GetRoutePreviewAsync()
        {
            var ocelotConfig = new OcelotConfigurationDto();
            // 获取全局变量
            var globalConfiguration = await _globalConfigurationService.GetGlobalConfigurationAsync();
            if (globalConfiguration != null)
            {
                if (globalConfiguration.Enabled)
                {
                    var globalConfigurationDto = globalConfiguration.Adapt<GlobalConfigurationDto>();
                    ocelotConfig.GlobalConfiguration = globalConfigurationDto;
                }
            }
            var projects = await _projectService.GetProjectsAsync();
            if (projects.Count == 0)
            {
                return "{}";
            }
            var allRoutes = new List<RouteDto>();
            foreach (var project in projects)
            {
                if (project.Routes.Count > 0)
                {
                    var routeDtos = project.Routes.OrderByDescending(o=>o.Sort).Adapt<List<RouteDto>>();
                    allRoutes.AddRange(routeDtos);
                }
            }

            var configRoutes = allRoutes.Adapt<List<ConfigRouteDto>>();
            ocelotConfig.Routes = configRoutes;

            var jSetting = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
            return JsonConvert.SerializeObject(ocelotConfig, Formatting.Indented, jSetting);
        }


        /// <summary>
        /// 查询路由具体信息
        /// </summary>
        /// <param name="projectIds">项目Id集合</param>
        /// <returns></returns>
        public async Task<List<RouteDto>> GetRouteByProjectIdsAsync(List<int> projectIds)
        {
            var route = await _sqlserverDB.Queryable<Route>().With(SqlWith.NoLock)
                 .Includes(o => o.RouteHostPorts)
                 .Includes(o => o.RouteProperties)
                 .Where(o => projectIds.Contains(o.ProjectId) && o.Enabled == true)
                 .ToListAsync();
            return route.Adapt<List<RouteDto>>();
        }

        /// <summary>
        /// 分页查询项目信息
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<SqlSugarPagedList<PageRouteResponse>> GetPageRouteAsync(PageRouteRequest request)
        {
            var enabled = request.Enabled.HasValue && request.Enabled.Value == 1;
            return await _sqlserverDB.Queryable<Route>().With(SqlWith.NoLock)
              .WhereIF(!string.IsNullOrWhiteSpace(request.UpstreamPathTemplate),
              o => o.UpstreamPathTemplate.Contains(request.UpstreamPathTemplate))
              .WhereIF(!string.IsNullOrWhiteSpace(request.DownstreamPathTemplate),
              o => o.DownstreamPathTemplate.Contains(request.DownstreamPathTemplate))
              .WhereIF(!string.IsNullOrWhiteSpace(request.RequestIdKey),
              o => o.RequestIdKey.Contains(request.RequestIdKey))
              .WhereIF(request.Enabled.HasValue,
              o => o.Enabled == enabled)
              .Where(o => o.ProjectId == request.ProjectId)
              .Select<PageRouteResponse>()
              .OrderByDescending(o => o.Id)
              .ToPagedListAsync(request.Current, request.PageSize);
        }

        /// <summary>
        /// 查询路由具体信息
        /// </summary>
        /// <param name="routeId"></param>
        /// <returns></returns>
        public async Task<RouteDto> GetRouteAsync(int routeId)
        {
            var route = await _sqlserverDB.Queryable<Route>().With(SqlWith.NoLock)
                 .Includes(o => o.RouteHostPorts)
                 .Includes(o => o.RouteProperties)
                 .Where(o => o.Id == routeId)
                 .FirstAsync();
            return route.Adapt<RouteDto>();
        }

        #endregion

        #region 新增

        /// <summary>
        /// 新增路由信息
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<int> InsertRouteAsync(RouteDto request)
        {
            var route = request.Adapt<Route>();
            var insertResult = await _sqlserverDB.InsertNav(route)
                .Include(o => o.RouteHostPorts)
                .Include(o => o.RouteProperties)
                .ExecuteCommandAsync();
            if (insertResult)
            {
                var now = DateTimeOffset.Now.ToUnixTimeSeconds();
                await _sqlserverDB.Updateable<Project>()
                    .SetColumns(o => o.UpdateTime == now).Where(o => o.Id == request.ProjectId).ExecuteCommandAsync();
                return route.Id;
            }
            else
            {
                throw Oops.Oh(ErrorCodes.INSERT_PROJECT_FAIL).StatusCode((int)ErrorCodes.INSERT_PROJECT_FAIL);
            }
        }

        #endregion

        #region 编辑

        /// <summary>
        /// 更新路由信息
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<int> UpdateRouteAsync(RouteDto request)
        {
            var route = request.Adapt<Route>();
            var result = await _sqlserverDB.DeleteNav(route)
                .Include(o => o.RouteHostPorts)
                .Include(o => o.RouteProperties)
                .ExecuteCommandAsync();
            if (result)
            {
                var now = DateTimeOffset.Now.ToUnixTimeSeconds();
                await _sqlserverDB.Updateable<Project>()
                    .SetColumns(o => o.UpdateTime == now).Where(o => o.Id == request.ProjectId).ExecuteCommandAsync();
                return await InsertRouteAsync(request);
            }
            else
            {
                throw Oops.Oh(ErrorCodes.UPDATE_PROJECT_FAIL).StatusCode((int)ErrorCodes.UPDATE_PROJECT_FAIL);
            }
        }

        /// <summary>
        /// 启用或禁用项目信息
        /// </summary>
        /// <param name="projectId">项目Id</param>
        /// <param name="enabled">是否有效</param>
        /// <returns></returns>
        public async Task<string> PatchProjectAsync(int projectId, bool enabled)
        {
            var result = await _sqlserverDB.Updateable<Project>()
                .SetColumns(it => new Project() { Enabled = enabled, UpdateTime = DateTimeOffset.Now.ToUnixTimeSeconds() })
                .Where(it => it.Id == projectId)
                .ExecuteCommandHasChangeAsync();
            if (result)
            {
                return $"{(enabled ? "启动" : "禁用")}项目成功";
            }
            else
            {
                var errorCode = enabled ? ErrorCodes.ENABLE_PROJECT_FAIL : ErrorCodes.DISABLE_PROJECT_FAIL;
                throw Oops.Oh(errorCode).StatusCode((int)errorCode);
            }
        }

        /// <summary>
        /// 启用或禁用路由信息
        /// </summary>
        /// <param name="routeId">路由Id</param>
        /// <param name="enabled">是否有效</param>
        /// <returns></returns>
        public async Task<string> PatchRouteAsync(int routeId, bool enabled)
        {
            var result = await _sqlserverDB.Updateable<Route>()
                .SetColumns(it => new Route() { Enabled = enabled })
                .Where(it => it.Id == routeId)
                .ExecuteCommandHasChangeAsync();
            if (result)
            {
                return $"{(enabled ? "启动" : "禁用")}路由成功";
            }
            else
            {
                var errorCode = enabled ? ErrorCodes.ENABLE_ROUTE_FAIL : ErrorCodes.DISABLE_ROUTE_FAIL;
                throw Oops.Oh(errorCode).StatusCode((int)errorCode);
            }
        }

        #endregion

        #region 删除

        /// <summary>
        /// 删除路由信息
        /// </summary>
        /// <param name="routeId">路由Id</param>
        /// <returns></returns>
        public async Task<string> DeleteRouteAsync(int routeId)
        {
            var result = await _sqlserverDB.DeleteNav<Route>(it => it.Id == routeId)
                .Include(o => o.RouteHostPorts)
                .Include(o => o.RouteProperties)
                .ExecuteCommandAsync();
            if (result)
            {
                return $"删除路由成功";
            }
            else
            {
                throw Oops.Oh(ErrorCodes.DELETE_ROUTE_FAIL).StatusCode((int)ErrorCodes.DELETE_ROUTE_FAIL);
            }
        }

        #endregion
    }
}